from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.contrib.auth.models import User 
from django.contrib.auth.decorators import user_passes_test, permission_required
from django.views.generic.list_detail import object_detail
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django.template.defaultfilters import slugify 
from django.utils.translation import gettext as _ 
from forms import * # IGNORE:W0614
from models import * # IGNORE:W0614


@user_passes_test(lambda u: u.has_perm('festivals.can_change_concert') or u.has_perm('festivals.can_add_concert')) 
def should_hide_concert_type(request, fest_id): #IGNORE:W0613
    """
    An AJAX helper for admin add/edit admin views for Concert model
    
    If festival type is 'Competition' ('C') then concert_type radio-buttons
    should be hidden, otherwise they should be shown
    """
    response = 'show'
    try:
        f = Festival.objects.get(pk=fest_id) #IGNORE:E1101
        if  f.fest_type != 'C':
            response = 'hide' 
    except ObjectDoesNotExist: #IGNORE:W0704
        pass # The Festival still isn't selected - do not hide
    return HttpResponse(response)


def make_unique_username(first_name, last_name):
    # Cleanup non-ascii chars
    first_name = slugify(first_name)
    last_name = slugify(last_name)
    
    # Calculate the base username
    username = "%s_%s" % (first_name[0], last_name)
    username = username.lower()
    # Check how many users are there with that username
    users = User.objects.filter(username__startswith=username).count()
    if users > 0: 
        username += str( (users+1) ) # Create a new, unique username
    return username
        

@permission_required('festivals.can_change_participant')
def edit_participant(request, part_id):
    participant = get_object_or_404(Participant, pk=part_id) 
    if request.method == 'POST':
        form = ParticipantForm(request.POST)
        if form.is_valid():
            # Get cleaned data first
            first_name = form.cleaned_data['first_name']
            last_name = form.cleaned_data['last_name']
            bio = form.cleaned_data['bio']
            
            # Save the first and last name
            user = participant.user
            user.first_name = first_name
            user.last_name = last_name
            user.save()
            
            # Save the bio
            participant.bio = bio
            participant.save()
            
            return HttpResponseRedirect('../')
    else:
        data = {
            'first_name': participant.get_first_name(),
            'last_name':  participant.get_last_name(),
            'bio':        participant.bio,
        }
        form = ParticipantForm(data)
    return render_to_response('admin/add_participant.html',
                              { 'form': form, 'original': participant},
                              context_instance=RequestContext(request)) 


@permission_required('festivals.can_add_participant')
def add_participant(request):
    if request.method == 'POST':
        form = ParticipantForm(request.POST)
        if form.is_valid():
            # Get cleaned data first
            first_name = form.cleaned_data['first_name']
            last_name = form.cleaned_data['last_name']
            bio = form.cleaned_data['bio']
            
            # Calculate the username and password and create the User
            username = make_unique_username(first_name, last_name) 
            password = User.objects.make_random_password(settings.RANDOM_PASSWORD_LENGTH)
            user = User.objects.create_user(username, "", password) # e-mail is empty, for now
            user.first_name = first_name
            user.last_name = last_name
            user.is_staff = True
            user.save()
            
            # Create a new Participant
            participant = Participant(user=user, bio=bio)
            participant.save()
            
            # Alert the admin that he has to notify the newly created
            # participant of his username/password - he can't see them again
            return render_to_response(
                'admin/participant_created.html',
                {
                    'participant': participant,
                    'username': username,
                    'password': password,
                },
            )
    else:
        form = ParticipantForm()
    return render_to_response('admin/add_participant.html',
                              { 'form': form, 'add': True, },
                              context_instance=RequestContext(request))


@permission_required('festivals.can_change_festival')
def generate_festival_program(request, fest_id):
    return object_detail(
        request,
        queryset = Festival.objects.all(), #IGNORE:E1101
        object_id = fest_id,
        template_name = 'admin/festivals/festival/generate_program.html',
        template_object_name = 'festival'
    )


@permission_required('festivals.can_change_concert')
def show_votes_score(request, conc_id):
    return object_detail(
        request,
        queryset = Concert.objects.all(), #IGNORE:E1101
        object_id = conc_id,
        template_name = 'admin/festivals/votes/show-current-score.html',
        template_object_name = 'concert'
    )


def get_performances_pending_votes(user):
    try:
        judge = user.participant_set.all()[0]
        
        # Get all the concerts where he's a judge
        concerts = judge.judged_concerts.all()
        concert_ids = [c.id for c in concerts]

        # Get the performances he already voted for
        voted_performances = Performance.objects.filter(vote__judge=judge) #IGNORE:E1101
        voted_performance_ids = [v.id for v in voted_performances]
        
        # Get the performances he didn't vote for
        performances_pending_votes = Performance.objects.filter( #IGNORE:E1101
            concert__id__in=concert_ids
        ).exclude(
            id__in=voted_performance_ids
        )
    except Exception: #IGNORE:W0704
        return None # The current user is not a participant
    return performances_pending_votes


def vote_now(request, performance_id):
    performances = get_performances_pending_votes(request.user)

    # Has the user already voted?
    performances = performances.filter(id=performance_id)
    if len(performances) == 0:
        raise Http404(_('You have already voted.'))

    if request.method == 'POST':
        form = VoteForm(request.POST)
        if form.is_valid():
            # Get cleaned data first
            vote_value = int(form.cleaned_data['vote'])
            
            # Save the Vote
            vote = Vote()
            vote.judge = request.user.participant_set.all()[0]
            vote.performance = performances[0]
            vote.vote = vote_value
            vote.save()
            
            return HttpResponseRedirect('../../')
    else:
        form = VoteForm()
    return render_to_response(
        'admin/festivals/votes/vote.html',
        {
            'form'        : form,
            'performance' : performances[0],
        },
        context_instance=RequestContext(request)
    )